package com.enation.app.javashop.buyer.api.trade;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dag.eagleshop.core.delivery.model.dto.JsonBean;
import com.dag.eagleshop.core.delivery.service.DeliveryManager;
import com.enation.app.javashop.core.base.SettingGroup;
import com.enation.app.javashop.core.client.member.MemberHistoryReceiptClient;
import com.enation.app.javashop.core.client.system.SettingClient;
import com.enation.app.javashop.core.member.service.MemberCouponManager;
import com.enation.app.javashop.core.promotion.coupon.model.dos.CouponDO;
import com.enation.app.javashop.core.promotion.pintuan.model.PintuanOrderDetailVo;
import com.enation.app.javashop.core.promotion.pintuan.service.PintuanOrderManager;
import com.enation.app.javashop.core.trade.TradeErrorCode;
import com.enation.app.javashop.core.trade.cart.model.dos.OrderPermission;
import com.enation.app.javashop.core.trade.order.model.dos.OrderItemsDO;
import com.enation.app.javashop.core.trade.order.model.dos.OrderLogDO;
import com.enation.app.javashop.core.trade.order.model.dos.OrderMemberDO;
import com.enation.app.javashop.core.trade.order.model.dos.TradeDO;
import com.enation.app.javashop.core.trade.order.model.dto.OrderDetailQueryParam;
import com.enation.app.javashop.core.trade.order.model.dto.OrderQueryParam;
import com.enation.app.javashop.core.trade.order.model.enums.*;
import com.enation.app.javashop.core.trade.order.model.vo.*;
import com.enation.app.javashop.core.trade.order.service.*;
import com.enation.app.javashop.core.trade.sdk.model.OrderDetailDTO;
import com.enation.app.javashop.core.trade.sdk.model.OrderVerificationDTO;
import com.enation.app.javashop.framework.context.UserContext;
import com.enation.app.javashop.framework.database.Page;
import com.enation.app.javashop.framework.exception.ServiceException;
import com.enation.app.javashop.framework.security.model.Buyer;
import com.enation.app.javashop.framework.util.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * 会员订单相关控制器
 *
 * @author Snow create in 2018/5/14
 * @version v2.0
 * @since v7.0.0
 */

@Api(description = "会员订单API")
@RestController
@RequestMapping("/trade/orders")
@Validated
public class OrderBuyerController {

    @Autowired
    private OrderQueryManager orderQueryManager;

    @Autowired
    private OrderOperateManager orderOperateManager;

    @Autowired
    private TradeQueryManager tradeQueryManager;

    @Autowired
    private MemberHistoryReceiptClient memberHistoryReceiptClient;

    @Autowired
    private OrderLogManager orderLogManager;

    @Autowired
    private OrderMemberManager orderMemberManager;

    @Autowired
    private MemberCouponManager memberCouponManager;

    @Autowired
    private PintuanOrderManager pintuanOrderManager;

    @Autowired
    private SettingClient settingClient;
    @Autowired
    private DeliveryManager deliveryManager;


    @ApiOperation(value = "查询会员订单列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "goods_name", value = "商品名称关键字", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "key_words", value = "关键字", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "order_status", value = "订单状态", dataType = "String", paramType = "query",
                    allowableValues = "ALL,WAIT_PAY,WAIT_SHIP,WAIT_ROG,CANCELLED,COMPLETE,WAIT_COMMENT,REFUND",
                    example = "ALL:所有订单,WAIT_PAY:待付款,WAIT_SHIP:待发货,WAIT_ROG:待收货," +
                            "CANCELLED:已取消,COMPLETE:已完成,WAIT_COMMENT:待评论,WAIT_CHASE:待追评，REFUND:售后中"),
            @ApiImplicitParam(name = "page_no", value = "页数", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "page_size", value = "条数", dataType = "int", paramType = "query"),
    })
    @GetMapping()
    public Page<OrderLineVO> list(@ApiIgnore String keyWords, @ApiIgnore String goodsName, @ApiIgnore String orderStatus,
                                  @ApiIgnore Integer pageNo, @ApiIgnore Integer pageSize) {

        try {
            if (StringUtil.isEmpty(orderStatus)) {
                orderStatus = "ALL";
            }
            OrderTagEnum.valueOf(orderStatus);
        } catch (Exception e) {
            throw new ServiceException(TradeErrorCode.E455.code(), "订单状态参数错误");
        }

        Buyer buyer = UserContext.getBuyer();
        OrderQueryParam param = new OrderQueryParam();
        param.setGoodsName(goodsName);
        param.setTag(orderStatus);
        param.setMemberId(buyer.getUid());
        param.setKeywords(keyWords);
        param.setPageNo(pageNo);
        param.setPageSize(pageSize);

        Page page = this.orderQueryManager.list(param);

        //货到付款的订单不允许线上支付
        List<OrderLineVO> list = page.getData();
        for (OrderLineVO order : list) {
            if (PaymentTypeEnum.COD.value().equals(order.getPaymentType())) {
                order.getOrderOperateAllowableVO().setAllowPay(false);
            }
            // 给拼团订单设置拼团订单VO，用于展示拼团人数
            if (PayStatusEnum.PAY_YES.value().equals(order.getPayStatus()) && OrderTypeEnum.pintuan.name().equals(order.getOrderType())
                    && ServiceStatusEnum.NOT_APPLY.value().equals(order.getServiceStatus())) {
                PintuanOrderDetailVo pintuanOrderDetail = pintuanOrderManager.getMainOrderBySn(order.getSn());
                order.setPintuanOrderDetail(pintuanOrderDetail);
            }
        }
        page.setData(list);

        return page;
    }


    @ApiOperation(value = "查询单个订单明细")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "order_sn", value = "订单编号", required = true, dataType = "String", paramType = "path")
    })
    @GetMapping(value = "/{order_sn}")
    public OrderDetailVO get(@ApiIgnore @PathVariable("order_sn") String orderSn) {
        OrderDetailQueryParam queryParam = new OrderDetailQueryParam();
        OrderDetailVO detailVO = this.orderQueryManager.getModel(orderSn, queryParam);

        if (detailVO.getNeedReceipt().intValue() == 1) {
            detailVO.setReceiptHistory(memberHistoryReceiptClient.getReceiptHistory(orderSn));
        }

        //货到付款的订单不允许线上支付
        if (PaymentTypeEnum.COD.value().equals(detailVO.getPaymentType())) {
            detailVO.getOrderOperateAllowableVO().setAllowPay(false);
        }

        if (detailVO.getPayStatus().equals(PayStatusEnum.PAY_NO.value())) {
            detailVO.setNeedPayMoney(0.00);
            detailVO.setWalletPayPrice(0.00);
            detailVO.setOnlinePayPrice(0.00);
        }

        return detailVO;
    }

    @ApiOperation(value = "虚拟商品订单查询核销码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "order_sn", value = "订单编号", required = true, dataType = "String", paramType = "path")
    })
    @GetMapping(value = "/virtual/{order_sn}")
    public OrderVerificationDTO queryVirtualCode(@ApiIgnore @PathVariable("order_sn") String orderSn) {
        Buyer buyer = UserContext.getBuyer();
        OrderVerificationDTO order = this.orderQueryManager.queryVirtualMessage(orderSn, buyer);
        return order;
    }


    @ApiOperation(value = "查询订单包裹信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "order_sn", value = "订单编号", required = true, dataType = "String", paramType = "path")
    })
    @GetMapping(value = "/package/{order_sn}")
    public List<List<OrderItemsVO>> packageInfo(@ApiIgnore @PathVariable("order_sn") String orderSn) {

        List<OrderItemsDO> orderItems = this.orderQueryManager.getOrderItemsByShipStatus(orderSn, ShipStatusEnum.SHIP_YES.value());
        // 1.解决老订单的订单详情中没有物流信息，去查订单表中的物流信息
        if (CollectionUtils.isEmpty(orderItems)) {
            OrderDetailDTO orderDetail = this.orderQueryManager.getModel(orderSn);
            if ((!StringUtil.isEmpty(orderDetail.getShipNo())) && orderDetail.getLogiId() > 0) {
                orderItems = this.orderQueryManager.getOrderItems(orderSn);
                for (OrderItemsDO orderItem : orderItems) {
                    orderItem.setShipStatus(orderDetail.getShipStatus());
                    orderItem.setLogiId(orderDetail.getLogiId());
                    orderItem.setLogiName(orderDetail.getLogiName());
                    orderItem.setShipNo(orderDetail.getShipNo());
                    orderItem.setShipTime(orderDetail.getShipTime());
                }
            }
        }
        // 2.给OrderItemsVO设置小程序默认展示属性show，最后发货的默认展示
        List<OrderItemsVO> orderItemsVOList = new ArrayList<>();
        int size = orderItems.size();
        for (int i = 0; i < size; i++) {
            OrderItemsDO orderItemsDO = orderItems.get(i);
            OrderItemsVO orderItemsVO = new OrderItemsVO();
            BeanUtil.copyProperties(orderItemsDO, orderItemsVO);
            if (i == size - 1) {
                orderItemsVO.setShow(true);
            } else {
                orderItemsVO.setShow(false);
            }
            orderItemsVOList.add(orderItemsVO);
        }
        // 3.将查询到的已发货商品详情按照物流单号分组返回
        TreeMap<String, List<OrderItemsVO>> result = orderItemsVOList.stream().collect(
                Collectors.groupingBy(
                        OrderItemsVO::getShipNo, TreeMap::new, toList()
                )
        );

        // 4.按照发货时间正序排序，最后发货的放在最后
        List<List<OrderItemsVO>> lists = new ArrayList<>(result.values());
        Collections.sort(lists, new Comparator<List<OrderItemsVO>>() {
            @Override
            public int compare(List<OrderItemsVO> o1, List<OrderItemsVO> o2) {
                if (o1.get(0).getShipTime() >= o2.get(0).getShipTime()) {
                    return 1;
                } else {
                    return -1;
                }
            }
        });
        return lists;
    }

    @ApiOperation(value = "确认收货")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "order_sn", value = "订单编号", required = true, dataType = "String", paramType = "path")
    })
    @PostMapping(value = "/{order_sn}/rog")
    public String rog(@ApiIgnore @PathVariable("order_sn") String orderSn) {

        Buyer buyer = UserContext.getBuyer();
        RogVO rogVO = new RogVO();
        rogVO.setOrderSn(orderSn);
        rogVO.setOperator(buyer.getUsername());

        orderOperateManager.rog(rogVO, OrderPermission.buyer);
        return "";
    }


    @ApiOperation(value = "未付款-取消订单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "order_sn", value = "订单编号", required = true, dataType = "String", paramType = "path"),
            @ApiImplicitParam(name = "reason", value = "取消原因", required = true, dataType = "String", paramType = "query"),
    })
    @PostMapping(value = "/{order_sn}/cancel")
    public String cancel(@ApiIgnore @PathVariable("order_sn") String orderSn, String reason) {

        Buyer buyer = UserContext.getBuyer();
        CancelVO cancelVO = new CancelVO();
        cancelVO.setOperator(buyer.getUsername());
        cancelVO.setOrderSn(orderSn);
        cancelVO.setReason(reason);
        orderOperateManager.cancel(cancelVO, OrderPermission.buyer);


        return "";
    }


    @ApiOperation(value = "查询订单状态的数量")
    @GetMapping(value = "/status-num")
    public OrderStatusNumVO getStatusNum() {
        Buyer buyer = UserContext.getBuyer();
        OrderStatusNumVO orderStatusNumVO = this.orderQueryManager.getOrderStatusNum(buyer.getUid(), null);
        return orderStatusNumVO;
    }


    @ApiOperation(value = "根据交易编号查询订单列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "trade_sn", value = "交易编号", required = true, dataType = "String", paramType = "path"),
    })
    @GetMapping(value = "/{trade_sn}/list")
    public List<OrderDetailVO> getOrderList(@ApiIgnore @PathVariable("trade_sn") String tradeSn) {
        Buyer buyer = UserContext.getBuyer();
        List<OrderDetailVO> orderDetailVOList = this.orderQueryManager.getOrderByTradeSn(tradeSn, buyer.getUid());
        return orderDetailVOList;
    }


    @ApiOperation(value = "根据交易编号或者订单编号查询收银台数据")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "trade_sn", value = "交易编号", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "order_sn", value = "订单编号", dataType = "String", paramType = "query")
    })
    @GetMapping(value = "/cashier")
    public CashierVO getCashier(@ApiIgnore String tradeSn, @ApiIgnore String orderSn) {

        String shipName, shipAddr, shipMobile, shipTel, shipProvince, shipCity, shipCounty, shipTown, payTypeText, sn,orderType, goodsImage;
        Integer goodNum = 0;
        Double needPayPrice, walletPayPrice;
        Long createTime;

        if (tradeSn != null) {

            TradeDO tradeDO = this.tradeQueryManager.getModel(tradeSn);
            //获取钱包支付金额
            walletPayPrice = tradeDO.getWalletPayPrice();
            shipName = tradeDO.getConsigneeName();
            shipAddr = tradeDO.getConsigneeAddress();
            shipMobile = tradeDO.getConsigneeMobile();
            shipTel = tradeDO.getConsigneeTelephone();
            shipProvince = tradeDO.getConsigneeProvince();
            shipCity = tradeDO.getConsigneeCity();
            shipCounty = tradeDO.getConsigneeCounty();
            shipTown = tradeDO.getConsigneeTown();
            needPayPrice = CurrencyUtil.sub(tradeDO.getTotalPrice(), walletPayPrice);
            payTypeText = tradeDO.getPaymentType();
            createTime=tradeDO.getCreateTime();
            // 根据交易单号查询 订单信息
            List<OrderDetailDTO> orderList = orderQueryManager.getOrderByTradeSn(tradeSn);
            for (OrderDetailDTO orderDetailDTO : orderList) {
                String itemsJson = orderDetailDTO.getItemsJson();
                JSONArray array = JSON.parseArray(itemsJson);
                // 商品数量
                goodNum = array.size() + goodNum;
            }
            OrderDetailDTO orderDetailDTO = orderList.get(0);
            String itemsJson = orderDetailDTO.getItemsJson();
            JSONArray array = JSON.parseArray(itemsJson);
            JSONObject json = JSON.parseObject(array.get(0).toString());
            // 商品图片
            goodsImage = json.getString("goods_image");
            // 订单号
            sn = orderDetailDTO.getSn();
            // 订单类型
            orderType = orderDetailDTO.getOrderType();
        } else if (orderSn != null) {

            OrderDetailQueryParam queryParam = new OrderDetailQueryParam();
            queryParam.setBuyerId(UserContext.getBuyer().getUid());

            OrderDetailVO detailVO = this.orderQueryManager.getModel(orderSn, queryParam);
            shipName = detailVO.getShipName();
            shipAddr = detailVO.getShipAddr();
            shipMobile = detailVO.getShipMobile();
            shipTel = detailVO.getShipTel();
            shipProvince = detailVO.getShipProvince();
            shipCity = detailVO.getShipCity();
            shipCounty = detailVO.getShipCounty();
            shipTown = detailVO.getShipTown();
            //获取钱包支付金额
            walletPayPrice = detailVO.getWalletPayPrice();
            //这里的needPayPrice理解为除了钱包支付其他支付方式需要支付的金额，因为钱包支付金额已经冻结
            needPayPrice = CurrencyUtil.sub(detailVO.getNeedPayMoney(), walletPayPrice);
            payTypeText = detailVO.getPaymentType();
            tradeSn=detailVO.getTradeSn();
            createTime=detailVO.getCreateTime();

            String itemsJson = detailVO.getItemsJson();
            JSONArray array = JSON.parseArray(itemsJson);
            // 商品数量
            goodNum = array.size();
            JSONObject json = JSON.parseObject(array.get(0).toString());
            // 商品图片
            goodsImage = json.getString("goods_image");
            // 订单号
            sn = orderSn;
            // 订单类型
            orderType = detailVO.getOrderType();
        } else {
            throw new ServiceException(TradeErrorCode.E455.code(), "参数错误");
        }

        CashierVO cashierVO = new CashierVO();
        cashierVO.setShipProvince(shipProvince);
        cashierVO.setShipCity(shipCity);
        cashierVO.setShipCounty(shipCounty);
        cashierVO.setShipTown(shipTown);
        cashierVO.setShipAddr(shipAddr);
        cashierVO.setShipMobile(shipMobile);
        cashierVO.setShipName(shipName);
        cashierVO.setNeedPayPrice(needPayPrice);
        cashierVO.setShipTel(shipTel);
        cashierVO.setPayTypeText(payTypeText);
        cashierVO.setTradeSn(tradeSn);
        //设置钱包支付金额
        cashierVO.setWalletPayPrice(walletPayPrice);

        cashierVO.setGoodNum(goodNum);
        cashierVO.setGoodsImage(goodsImage);
        cashierVO.setOrderSn(sn);
        cashierVO.setOrderType(orderType);

        //获取设置中订单的自动取消时间，单位为分钟
        String settingVOJson = this.settingClient.get(SettingGroup.TRADE);
        OrderSettingVO settingVO = JsonUtil.jsonToObject(settingVOJson, OrderSettingVO.class);
        long payTimeLeft = settingVO.getCancelOrderDay() * 60L;

        cashierVO.setPayTimeLeft(payTimeLeft);
        cashierVO.setOrderCreateTime(createTime);
        return cashierVO;
    }


    @ApiOperation(value = "订单流程图数据", notes = "订单流程图数据")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "order_sn", value = "订单sn", required = true, dataType = "String", paramType = "path"),
    })
    @GetMapping(value = "/{order_sn}/flow")
    public List<OrderFlowNode> getOrderStatusFlow(@ApiIgnore @PathVariable(name = "order_sn") String orderSn) {
        List<OrderFlowNode> orderFlowList = this.orderQueryManager.getOrderFlow(orderSn);
        return orderFlowList;
    }

    @ApiOperation(value = "查询订单日志")
    @ApiImplicitParams({@ApiImplicitParam(name = "order_sn", value = "订单编号", required = true, dataType = "String", paramType = "path")})
    @GetMapping(value = "/{order_sn}/log")
    public List<OrderLogDO> getList(@ApiIgnore @PathVariable("order_sn") String orderSn) {
        List<OrderLogDO> logDOList = this.orderLogManager.listAll(orderSn);
        return logDOList;
    }


    @ApiOperation(value = "查询用户订单汇总")
    @GetMapping(value = "/orderCount")
    public OrderMemberDO getMemberOrderCount() {
        Buyer buyer = UserContext.getBuyer();
        OrderMemberDO orderMember = orderMemberManager.getOrderMember(buyer.getUid());
        if (orderMember == null) {
            orderMemberManager.orderStatistic(buyer.getUid());
            orderMember = orderMemberManager.getOrderMember(buyer.getUid());
        }
        return orderMember;
    }



    @ApiOperation(value = "订单分享详情信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "order_sn", value = "订单编号", required = true, dataType = "String", paramType = "path")
    })
    @GetMapping(value = "/shareOrder/{order_sn}")
    public ShareOrderVO shareOrder(@ApiIgnore @PathVariable("order_sn") String orderSn) {

        ShareOrderVO shareOrderVO = new ShareOrderVO();
        // 订单详情
        OrderDetailQueryParam queryParam = new OrderDetailQueryParam();
        OrderDetailVO detailVO = this.orderQueryManager.getModel(orderSn, queryParam);
        shareOrderVO.setOrderDetail(detailVO);
        shareOrderVO.setCanReceive(false);
        // 红包分享开关（店铺开关）
        String sellerCouponStatus = DictUtils.getDictValue(null, "SELLER_SHARE_COUPON_"+detailVO.getSellerId(), "SELLER_SHARE_COUPON");
        if(StringUtils.isNotEmpty(sellerCouponStatus) && sellerCouponStatus.equals("CLOSE")){
            return shareOrderVO;
        }
        // 可领取优惠券
        CouponDO couponDO=memberCouponManager.getOrderShareCoupon(orderSn,detailVO.getSellerId());
        if(couponDO!=null){
            shareOrderVO.setCanReceive(true);
            shareOrderVO.setCoupon(couponDO);
        }

        shareOrderVO.setDiscountPrice(detailVO.getDiscountPrice());
        return shareOrderVO;
    }


}


